<html>
<head>
<title>Lightest Documentation</title>
<style type="text/css">
body {
    margin-left: 5%;
    margin-right: 5%;
}
dt {
    font-weight: bolder;
}
dd {
    margin-top: 10px;
    margin-bottom: 10px;
}
pre {
    margin: 10px;
    padding: 10px;
    background-color: #eaeaea;
}
code {
    padding: 2px;
    background-color: #dfd;
}
table {
    border-collapse: collapse;
    border: solid 1px black;
}
th, td {
    border: solid 1px grey;
    padding: 5px;
}
.highlight {
    background-color: #eea;
}
.deprecated {
    font-style: italic;
    color: #c99;
}
</style>
</head>

<body>

<h1>Lightest Documentation</h1>

<p>This documentation provides some useful reference material related to using Lightest. For a more hands-on reference, try the <a href="lightest-tutorial.html">Lightest tutorial</a>!</p>

<h2>What Is Lightest?</h2>

<p>Lightest is a task-oriented functional and integration test automation framework built on Groovy and TestNG. It's a "framework framework" that is intended to greatly simplify the process of creating your own custom framework by implementing the testcase management, execution, and reporting for you - all you do is define the test environment and write the tasks!</p>

<p>You might want to try Lightest if:</p>

<ul>
<li>You want to whip up a test automation solution in a flash</li>
<li>You find you are using a unit testing framework for functional or integration level testing</li>
<li>You are testing a GUI or web application</li>
<li>You want to transition from an unscripted test automation solution to a scripted one</li>
<li>Your test automation framework needs to use Java libraries</li>
<li>You love Groovy</li>
<li>You love TestNG</li>
<li>You love staying <a href="http://en.wikipedia.org/wiki/DRY">DRY</a></li>
</ul>

<p>The <a href="http://code.google.com/p/lightest">Lightest project</a> is hosted on Google Code. You may download releases, browse the source, or file issues there.</p>

<h2>Running Lightest</h2>

<p>The Lightest framework comes with a runner packaged in an executable JAR. The standalone distribution includes all required dependencies; no external libraries are needed. Tests are run from the command line by specifying a configuration file (see below for syntax) and <em>either</em> a list of Groovy test files (which subclass <code>LightestTestCase</code>, also see below) <em>or</em> a TestNG suite XML file which specifies the test classes and groups to run. The most important configuration to get right is the <code>classPaths</code> element; most other configurations have sensible defaults.</p>

<pre>$ java -jar lightest-core-0.2-standalone.jar config.txt MyTest.groovy MyTest2.groovy</pre>

<pre>$ java -jar lightest-core-0.2-standalone.jar config.txt testng.xml</pre>

<p>You can start the runner in interactive mode by providing the right switch:</p>

<pre>$ java -jar lightest-core-0.2-standalone.jar --interactive config.txt MyTest.groovy</pre> 

<p>Lightest requires at least Java <code>1.5</code> . Surprisingly, you shouldn't need to install Groovy on your machine to run Lightest. However, you'll probably want to have a reasonably recent version (<code>1.5.4</code> or later) to use when developing your tasks. If you don't have it, <a href="http://groovy.codehaus.org/Download">get it here</a>!</p>

<p>The runner produces an HTML report, which in turn is generated from an XML report. HTML is probably the most convenient reporting format; however, it is possible to customize Lightest to create reports in other formats. See <a href="lightest-tutorial.html">the tutorial</a> for screenshots of the reports that are produced.</p>

<h2>Configuration File Reference</h2>

<p>The configuration file specified as the first argument to the runner follows a Groovy builder syntax, with the <code>config</code> element as its root node.</p>

<table>
<tr><th>Element</th>
    <th>Description</th>
    <th>Example</th>
</tr>
<tr><td>classPaths</td>
    <td><p>Contains <code>path</code> elements which enumerate the class paths that should be used to locate task, testcase, preference, and environment classes. By default, the current directory <code>.</code> is included in the path. There is no limit to the number of entries.</p>
        <p>You will probably get an error if any class specified in a configuration cannot be loaded from the class paths set here.</p></td>
    <td><pre>config {
...
    classPaths {
        path ('/path/to/tasks')
        path ('../path/to/tests')
    }
...
}</pre></td>
</tr>
<tr><td>outputDir</td>
    <td>Specifies the report output directory. The report files will be placed directly in this directory. If unspecified, by default the report will be created in the <em>lightest-report</em> directory in the directory where the test runner was invoked. If more than one directory is specified, only the first entry will be used.</td>
    <td><pre>config {
...
    outputDir ('/path/to/report')
...
}</pre></td>
</tr>
<tr><td>prefs</td>
    <td>Specifies name-value pairs for preferences to be shared across all tests being configured in this run. The preferences must have a corresponding class, which has publicly-accessible properties to match the preference names. There should be only one <code>prefs</code> element.</td>
    <td><pre>config {
...
    prefs (class: 'my.package.Preferences') {
        timeout (5000)
        corpus ('main')
    }
...
}</pre></td>
</tr>
<tr><td>envs</td>
    <td><p>Enumerates test environments that are available to the tests being configured in this run. Tests may be run concurrently across these environments.</p>
        <p>All environments correspond to a single class, but have name-value pairs which may differentiate them. Testcases and tasks are able to access these values for the purpose of interacting with their respective environment. These name-value pairs must match properties of the environment class. Each environment must have a unique <code>String</code> identifier.</p>
        <p>There should be only one <code>envs</code> element. If none are specified, 3 default environments identified by <code>unspecified1</code>, <code>unspecified2</code>, and <code>unspecified3</code> will be provided.</p></td>
    <td><pre>config {
...
    envs (class: 'my.package.Environment') {
        env (id: 'windows') {
            homeDir ('C:\\Documents and Settings\\me')
            appName ('my.app')
        }
        env (id: 'linux') {
            homeDir ('/home/me')
            appName ('my.app')
        }
        env (id: 'macos') {
            homeDir ('/Users/me')
            appName ('my.app')
        }
    }
...
}</pre></td>
</tr>
<tr><td>reporter</td>
    <td>You may specify a reporter class that will be used instead of the default <code>LightestReporter</code> to generate the report output. This class should both extend <code>LightestTestListener</code> and implement <code>ILightestReporter</code> . Currently only one <code>reporter</code> element is supported, though this may change.</td>
    <td><pre>config {
...
    reporter (class: 'my.package.Reporter')
...
}</pre></td>
</tr>
<tr><td>dispatcherAssignmentStrategy</td>
    <td>You may specify a strategy class that will be used instead of the default <code>SimpleDispatcherAssignmentStrategy</code> to decide how task dispatchers (which are associated with test environments) get assigned to testcase classes. This class must implement <code>IDispatcherAssignmentStrategy</code>, and may for convenience extend <code>QueuedDispatcherAssignmentStrategy</code> to handle concurrency. There should be only one <code>dispatcherAssignmentStrategy</code> element.</td>
    <td><pre>config {
...
    dispatcherAssignmentStrategy (class: 'my.package.Strategy')
...
}</pre></td>
</tr>
</table>

<h2>Core Classes Overview</h2>

<h3>SimpleApi</h3>

<p>The <code>SimpleApi</code> class (<code>com.googlecode.lightest.core.SimpleApi</code>) provides a convenient way to define the set of tasks that are available to a given testcase. It can search one or more Java package paths for tasks by name, and returns the first task found. By default, all tasks in the current working directory of the test runner are included by <code>SimpleApi</code> instances.</p>

<p>Use <code>addPackage(String packageName)</code> to add a new package path to the API. For example, if your tasks are defined in the package <code>com.sample.tasks</code>, you could do:</p>

<pre>
def api = new SimpleApi()
api.addPackage('com.sample.tasks')
</pre>

<p>Or simply:</p>

<pre>def api = new SimpleApi('com.sample.tasks')</pre>

<p><code>SimpleApi</code> implements <code>IDomainSpecificApi</code>, specifically its <code>getTask(String name)</code> method. You may use a custom implementation of this interface that doesn't obtain tasks by package at all, and uses some other mechanism.</p>

<h3>LightestTestCase</h3>

<p>All Lightest tests extend <code>LightestTestCase</code> (<code>com.googlecode.lightest.core.LightestTestCase</code>), which is responsible for properly interpreting tasks specified with the builder syntax in its test methods. Subclasses should call <code>setApi(IDomainSpecificApi api)</code> before invoking any tasks. This can be done in the constructor of the test class, or in a <code>@Before</code> method. In its simplest form:</p>

<pre>
class MyTest extends LightestTestCase {

    MyTest() {
        setApi(new SimpleApi())
    }
}
</pre>

<p><code>LightestTestCase</code> itself subclasses <code>GroovyTestCase</code> so that the standard <a href="http://groovy.codehaus.org/api/groovy/util/GroovyTestCase.html">Groovy test assertions</a> (extensions to the JUnit 3.8 assertions) are available. Note however that Lightest tests are <strong>not</strong> run by a JUnit runner; you must always use the <code>@Test</code> annotation to mark test methods and <code>@Before</code> / <code>@After</code> to mark fixture setup and teardown methods, respectively.</p>

<p>You can access the test environment (implementing <code>ITestEnvironment</code>) assigned to the testcase in any given test method, via the dispatcher:</p>

<pre>
    @Test
    void myTest() {
        def env = getDispatcher().getEnvironment()
        ...
        env.myLocalVar = 'foo'
        ...
    }
</pre>

<p>You can add local values to the environment in the scope of any test method, and these can be accessed by any tasks that are invoked, via the environment. Local values will be cleared from the environment after the method finishes. Just be sure you don't inadvertantly clobber a non-local value!</p>

<h3>LightestTask</h3>

<p>Each task used in a testcase should have as its implementation a corresponding subclass of <code>LightestTask</code> (<code>com.googlecode.lightest.core.LightestTask</code>). The task is responsible for performing some action, and populating a result object (see the next section) depending on whether the action succeeded or failed. Subclasses of <code>LightestTask</code> only have to implement a single method, <code>doPerform(ITaskResult result)</code>:</p>

<pre>
class MyTask extends LightestTask {

    void doPerform(ITaskResult result) {
        println 'Been there, done that.'
        result.fail()
    }
}
</pre>

<p>Three key fields are available for inspection in task classes - <code>config</code>, <code>prefs</code>, and <code>env</code> .<p>

<p>The <code>config</code> object is essentially a <code>groovy.util.Node</code> from which the parameters to the task may be accessed. Attributes are accessed using the <code>.'@attributeName'</code> notation, and values can be accessed with <code>.nodeValue()</code> . For example:</p>

<em>MyTest.groovy</em>
<pre>
    @Test
    void myTest() {
        MyTask (attr1: 'foo', attr2: 'bar, 'baz')
    }
</pre>
    
<em>MyTask.groovy</em>
<pre>
    void doPerform(ITaskResult result) {
        println config.'@attr1'     // prints "foo"
        println config.'@attr2'     // prints "bar"
        println config.nodeValue()  // prints "baz"
    }
</pre>

<p>Two attributes on <code>config</code> have special meaning in the context of Lightest - <code>description</code> and <code>breakpoint</code>. If set, the String representation of <code>description</code> will be automatically visible with the task in the report. If for a given task <code>breakpoint</code> is set to any value that evaluates to <code>true</code>, the test will pause at that task if the runner is in interactive mode. You don't have to do anything in the task definition for these features to work.</p>

<p>Any preference values specified in the configuration file may be accessed from <code>prefs</code>. And any environment values may be accessed from <code>env</code>. Of course, local environment values may also be set on <code>env.</code>.</p>

<h3>ITaskResult</h3>

<p>Executing a task always produces a <code>ITaskResult</code> (<code>com.googlecode.lightest.core.ITaskResult</code>). The values populated on this object will appear in the report for the test run. The important values to consider setting are <code>status</code>, <code>message</code>, <code>responseData</code>, and <code>links</code> . The <code>ITaskResult</code> object is passed into the <code>doPerform()</code> method, and should be populated therein.</p>

<p>The <code>status</code> of the result is what determines whether the task succeeded or failed. By default, the status is set to indicate success (<code>STATUS_OK</code>). Setting it to anything else indicates failure at some level. In order of increasing severity, you can invoke <code>flag()</code>, <code>fail()</code>, or <code>doom()</code> on the result object to do this.</p>

<p>Use <code>setMessage(String message)</code> to set an informational message to be displayed in the report. In particular, display any information related to why the task may have failed.</p>

<p>Use <code>setResponseData(String data)</code> to set larger chunks of text that may have been produced in performing the task.</p>

<p>Finally, use <code>addLink(String link)</code> to add a link to related resources, such as documents or screenshots. The link text will appear in the report, exactly as specified using this method. Multiple links may be specified.</p>

<h2>Other Resources</h2>

<ul>
<li><a href="apidocs/index.html">Lightest API</a></li>
<li><a href="lightest-tutorial.html">Lightest Tutorial</a></li>
<li><a href="http://code.google.com/p/lightest">Lightest Project Page</a></li>
<li><a href="http://stressfreetesting.com/lightest">Lightest @ stressfreetesting.com</a></li>
<li><a href="http://testng.org/doc/documentation-main.html">TestNG Documentation</a></li>
<li><a href="http://groovy.codehaus.org/api/">Groovy API</a></li>
</ul>

<p><em>- Haw-Bin Chai (hbchai @t gmail d0t com)</em></p>

<br />
<br />
<br />
<br />

</body>
</html>